package com.smart.home.service.impl;

import com.smart.home.constant.HomeConstant;
import com.smart.home.constant.RoleConstant;
import com.smart.home.context.UserContext;
import com.smart.home.dto.Home.DeleteMemberDto;
import com.smart.home.dto.Home.GrantUserDto;
import com.smart.home.dto.Home.HomeDto;
import com.smart.home.entity.HomeMembers;
import com.smart.home.entity.Homes;
import com.smart.home.exception.BusinessException;
import com.smart.home.mapper.DevicesMapper;
import com.smart.home.mapper.HomeMapper;
import com.smart.home.mapper.HomeMemberMapper;
import com.smart.home.service.DevicesService;
import com.smart.home.service.HomeService;
import com.smart.home.vo.HomesListVO;
import com.smart.home.vo.HomesVO;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Slf4j
public class HomeServiceImpl implements HomeService {
    @Autowired
    private HomeMapper homeMapper;

    @Autowired
    private HomeMemberMapper homeMemberMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private DevicesMapper devicesMapper;


    /**
     * 创建相关家庭
     * 同时对于相关用户创建家庭进行限制,多张表操作进行事务处理，
     * TODO 创建一个家庭redis的role功能对于owner只能有一个对于管理者取决于用户需要多少这里限定3个不能多余这个
     * @param homeDto
     */
    @Override
    @Transactional
    public void CreateHome(HomeDto homeDto) {
        final Integer USER_CREAT_HOME_LIMIT = 5;

        Homes homes = new Homes();
        HomeMembers homeMembers =new HomeMembers();


        BeanUtils.copyProperties(homeDto,homes);


        homeMapper.CreateHome(homes);


        //手动加入不使用apo对于后序用户加入的注入有问题
         homeMembers.setHomeId(homes.getId());
         homeMembers.setRole(RoleConstant.OWNER);
        homeMemberMapper.CreateHomeMember(homeMembers);


        String key = "home:"+ UserContext.getUserId();
        Integer count =(Integer) redisTemplate.opsForValue().get(key);
        if (count == null){
            count = 0;
        }

        if(count > USER_CREAT_HOME_LIMIT){
            throw new BusinessException(HomeConstant.USER_CREATE_HOME);
        }

        redisTemplate.opsForValue().increment(key,1);

    }

    /**
     * 加入家庭，加入那个家庭，授予什么角色,在俩张表同时修改
     * @param homeDto
     */
    @Override
    public void JoinHome(HomeDto homeDto) {
        Homes homes = new Homes();
        HomeMembers homeMembers =new HomeMembers();
        BeanUtils.copyProperties(homeDto,homes);


        homeMembers.setHomeId(homes.getId());
        homeMembers.setRole(RoleConstant.MEMBER);
        homeMemberMapper.JoinHomeMember(homeMembers);

    }

    /**
     * 返回用户所有家庭,通过上下文获取用户id
     * TODO 这里看看能不能使用缓存来建设相关数据查询压力
     * @return
     */
    @Override
    public List<HomesVO> GetUerHome() {
        Long  userId = UserContext.getUserId();
        log.info("返回用户所有家庭:{}",userId);
        List<HomesVO> homesVO = homeMapper.GetUerHome(userId);

        return homesVO;
    }

    /**
     * 返回用户所有家庭列表
     * TODO 这里看看能不能使用缓存来建设相关数据查询压力
     * @return
     */
    @Override
    public List<HomesListVO> GetUerHomeList() {
        Long  userId = UserContext.getUserId();
        List<HomesListVO> homesListVOS = homeMapper.GetUerHomeList(userId);

        return homesListVOS;
    }

    /**
     * 授权用户
     * @param grantUserDto
     */
    @Override
    public void GrantUser(GrantUserDto grantUserDto) {


        Long ownerId = homeMapper.getIdByHomeName(grantUserDto.getHomeId());
        if(ownerId != UserContext.getUserId()){
            throw new BusinessException(HomeConstant.USER_NOT_OWNER);
        }


        String Role = homeMemberMapper.GetRoleByHomeIdAndUserId(grantUserDto.getHomeId(),grantUserDto.getTargetUserId());
        if(Role == null){
            throw new BusinessException(HomeConstant.USER_NOT_EXIST);
        }
        String role = homeMemberMapper.GetRoleByHomeIdAndUserId(grantUserDto.getHomeId(),grantUserDto.getTargetUserId());
        if(role == null){
            throw new BusinessException(HomeConstant.USER_NOT_EXIST);
        }

        //判断权限等级是否足够
        if( (Integer)redisTemplate.opsForValue().get(Role)< (Integer) redisTemplate.opsForValue().get(role)){
            throw new BusinessException(HomeConstant.USER_NOT_ROLE);
        }

        role = grantUserDto.getRole();
        homeMemberMapper.GrantUser(grantUserDto.getHomeId(),grantUserDto.getTargetUserId(),role);

    }

    /**
     * 删除家庭
     * @param homeId
     */
    @Override
    @Transactional
    public void DeleteHome(Long homeId) {
        Long userId = UserContext.getUserId();
        if (userId.equals(homeMapper.getIdByHomeName(homeId))){
            throw new RuntimeException(HomeConstant.USER_NOT_OWNER);
        }

        devicesMapper.deleteByHomeId(homeId);
        homeMemberMapper.DeleteHome(homeId);
        homeMapper.DeleteHome(homeId);
    }

    /**
     * 退出家庭
     * @param homeId
     */
    @Override
    public void LogoutHome(Long homeId) {
        Long userId = UserContext.getUserId();
        String role = homeMemberMapper.GetRoleByHomeIdAndUserId(homeId, userId);
        if(role.equals(RoleConstant.OWNER)){
            DeleteHome(homeId);
        }else {
            homeMemberMapper.LogoutHome(homeId, userId);
        }
    }

    /**
     * 删除成员
     * @param deleteMemberDto
     */
    @Override
    public void DeleteMember(DeleteMemberDto deleteMemberDto) {
        String TargetRole = homeMemberMapper.GetRoleByHomeIdAndUserId(deleteMemberDto.getHomeId(), deleteMemberDto.getTargetUserId());
        String role = homeMemberMapper.GetRoleByHomeIdAndUserId(deleteMemberDto.getHomeId(),UserContext.getUserId());

        Integer currentRoleLevel =(Integer) redisTemplate.opsForValue().get(role);
        Integer targetRoleLevel =(Integer) redisTemplate.opsForValue().get(TargetRole);
        if(currentRoleLevel < targetRoleLevel){
            throw new BusinessException(HomeConstant.USER_NOT_ROLE);
        }
        homeMemberMapper.LogoutHome(deleteMemberDto.getHomeId(),deleteMemberDto.getTargetUserId());
    }
}


















